<html>
<head><meta charset="utf-8"><title>non-register parameters · project-inline-asm · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/index.html">project-inline-asm</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html">non-register parameters</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="200411468"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200411468" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200411468">(Jun 10 2020 at 12:53)</a>:</h4>
<p>(Split out of previous thread, as its veering a long way off topic).  Consider the C</p>
<div class="codehilite"><pre><span></span><code><span class="k">static</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="nf">write_flags</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">flags</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">asm</span> <span class="k">volatile</span> <span class="p">(</span><span class="s">&quot;push %0; popf&quot;</span> <span class="o">::</span> <span class="s">&quot;rme&quot;</span> <span class="p">(</span><span class="n">flags</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div>


<p>In this case, the push instruction can be encoded using a register, an immediate (but only in the i32 range), or a memory operand.  An immediate is already possible with the <code>const</code> notation, but I can't see a way of expressing "register or immediate".</p>
<p>In general, LLVM is pretty good (in C at least) of avoiding register operands when possible.  It reduces register pressure in the surrounding code.</p>



<a name="200411805"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200411805" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200411805">(Jun 10 2020 at 12:56)</a>:</h4>
<p>For memory operands in general, anything on the stack can be expressed with an rsp/rbp relative reference, which again reduces the register pressure required to use the asm block</p>



<a name="200412159"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200412159" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200412159">(Jun 10 2020 at 12:59)</a>:</h4>
<p>and consider examples such as</p>
<div class="codehilite"><pre><span></span><code><span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">sz</span><span class="p">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="n">cacheline_size</span> <span class="p">)</span>
    <span class="k">asm</span> <span class="p">(</span><span class="s">&quot;clwb %0&quot;</span> <span class="o">::</span> <span class="s">&quot;m&quot;</span><span class="p">(</span><span class="n">ptr</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>
</code></pre></div>


<p>which is optimised to <code>clwb (%rdi,%rax,1)</code> using the SIB form</p>



<a name="200412660"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200412660" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200412660">(Jun 10 2020 at 13:03)</a>:</h4>
<p>I don't think in general it is interesting to say "use this exact encoding form".  If the programmer needs careful control over the encoding, they should write it in longhand so the results aren't ambiguous.  The common case is "this can be in memory", with the implication that the optimiser should pick the best option available.</p>



<a name="200456480"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200456480" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200456480">(Jun 10 2020 at 18:25)</a>:</h4>
<p>This is actually much more complicated than it seems. Have a look at LLVM's <a href="https://llvm.org/docs/LangRef.html#supported-constraint-code-list">constraint codes</a> and note how there are tons of different variants, e.g. "I: An immediate integer between 0 and 31."</p>



<a name="200456530"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200456530" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200456530">(Jun 10 2020 at 18:25)</a>:</h4>
<p>It's the same with memory addressing modes such as "Q: A memory address operand with a base address and a 12-bit immediate unsigned displacement."</p>



<a name="200456649"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200456649" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200456649">(Jun 10 2020 at 18:26)</a>:</h4>
<p>This is the main reason why memory constraints were excluded from the initial version of <code>asm!</code>, there's just too many different variants.</p>



<a name="200460289"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200460289" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200460289">(Jun 10 2020 at 18:54)</a>:</h4>
<p>You've already got that problem with restricted integer ranges</p>
<div class="codehilite"><pre><span></span><code><span class="n">asm</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;shrq ${nr}, {tmp:r}&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w">     </span><span class="n">tmp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">out</span><span class="p">(</span><span class="n">reg</span><span class="p">)</span><span class="w"> </span><span class="n">_</span><span class="p">,</span><span class="w"></span>
<span class="w">     </span><span class="n">nr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="mi">72</span><span class="p">,</span><span class="w"></span>
<span class="w">     </span><span class="n">options</span><span class="p">(</span><span class="n">att_syntax</span><span class="p">)</span><span class="w"></span>
<span class="p">);</span><span class="w"></span>
</code></pre></div>


<p>assembles fine, but doesn't do what you'd expect.  (I'm half surprised that LLVM doesn't complain about the ${nr} being outside of the legitimate range.)</p>



<a name="200485139"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200485139" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200485139">(Jun 10 2020 at 22:22)</a>:</h4>
<p>Having thought about this some more, all immediate operands can be expressed as an integer typecast of 8/16/32/64 signed or unsigned, with the exception of an explicit SIB Scale, which must be in the range 0..3</p>



<a name="200485303"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200485303" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200485303">(Jun 10 2020 at 22:23)</a>:</h4>
<p>the "must be limited to 31/63" constraints are for shifts such as the example above, but the encoding of the instruction is valid with a full 8 bits, hence the lack of complaint by LLVM until you change the number to be &gt;255</p>



<a name="200485512"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200485512" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200485512">(Jun 10 2020 at 22:25)</a>:</h4>
<p>you can probably do everything necessary (optimisation wise) by supporting something such as <code>nr = in(reg, u8) foo</code> meaning "either a register, or a byte immediate".</p>



<a name="200485857"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200485857" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200485857">(Jun 10 2020 at 22:28)</a>:</h4>
<p>That said, you probably want a general int constraint for the common case, where both signed 8 or 32 will do (or 16 with the data size prefix)</p>



<a name="200487404"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200487404" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200487404">(Jun 10 2020 at 22:44)</a>:</h4>
<p>Have a look at the constraints on other architectures, not just x86. It can get very hairy.</p>



<a name="200487549"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200487549" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200487549">(Jun 10 2020 at 22:46)</a>:</h4>
<p>j: An immediate integer between 0 and 65535 (valid for MOVW)<br>
I: An immediate integer valid for a data-processing instruction.<br>
J: An immediate integer between -4095 and 4095.<br>
K: An immediate integer whose bitwise inverse is valid for a data-processing instruction. (Can be used with template modifier “B” to print the inverted value).<br>
L: An immediate integer whose negation is valid for a data-processing instruction. (Can be used with template modifier “n” to print the negated value).<br>
M: A power of two or a integer between 0 and 32.</p>



<a name="200487594"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200487594" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200487594">(Jun 10 2020 at 22:46)</a>:</h4>
<p>And that's just for ARM.</p>



<a name="200489235"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200489235" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200489235">(Jun 10 2020 at 23:04)</a>:</h4>
<p>All of those problems already exist with the <code>const</code> keyword.  There is no protection from putting an inappropriate integer into the asm.<br>
Given this, is a single <code>in(reg, int)</code> with similarly no protections too hard to do?</p>



<a name="200489465"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200489465" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200489465">(Jun 10 2020 at 23:07)</a>:</h4>
<p>Well the point of these restricted immediate classes is that you want to fall back to a regsiter if your immediate does not fit in that class.</p>



<a name="200489517"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200489517" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200489517">(Jun 10 2020 at 23:08)</a>:</h4>
<p>There's actually a general RISC/CISC divide here.  Its not common to find instruction in RISC which can be encoded in multiple different ways like this, whereas it's the norm in x86.</p>



<a name="200489542"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200489542" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200489542">(Jun 10 2020 at 23:08)</a>:</h4>
<p>Actually it's quite common, just look at the ADD instruction</p>



<a name="200489554"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200489554" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200489554">(Jun 10 2020 at 23:08)</a>:</h4>
<p>You can do reg + reg or reg + immediate.</p>



<a name="200489582"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200489582" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200489582">(Jun 10 2020 at 23:09)</a>:</h4>
<p>What you want in this case is "try to encode the value as an immediate if it is a constant and fits the instruction's constraints, otherwise use a regsiter"</p>



<a name="200490087"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200490087" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200490087">(Jun 10 2020 at 23:16)</a>:</h4>
<p>hmm yes, and I suppose the only option is for the programmer to tell you want the real constraint is</p>



<a name="200490178"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216763-project-inline-asm/topic/non-register%20parameters/near/200490178" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Andrew Cooper <a href="https://rust-lang.github.io/zulip_archive/stream/216763-project-inline-asm/topic/non-register.20parameters.html#200490178">(Jun 10 2020 at 23:17)</a>:</h4>
<p>not as if it's feasible to ask the backend</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>